<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>数据驱动视图</title>
</head>

<body>
  <div id="app">
    <p>{{ name.firstName }}</p>
  </div>
  <script>
    class Vue {
      constructor($options) {
        this._data = $options.data
        this.compile($options.el, this)
      }
      compile(el, vm) {
        vm._el = document.querySelector(el)
        const cloneNode = vm._el.cloneNode(true)
        this.render(cloneNode, vm)
        // 新的替换掉旧的
        vm._el.parentNode.replaceChild(cloneNode, document.querySelector('#app'))
      }
      render(template, vm) {
        const childNodes = template.childNodes
        const regMustache = /\{\{\s*(\S+)\s*\}\}/
        for (let i = 0; i < childNodes.length; i++) {
          const type = childNodes[i].nodeType
          if (type === 3) {
            let nodeValue = childNodes[i].nodeValue
            nodeValue = nodeValue.replace(regMustache, (node, value) => {
              let val = this.getValueByPath(vm._data, value)
              return val
            })
            childNodes[i].nodeValue = nodeValue
          } else {
            this.render(childNodes[i], vm)
          }
        }
      }
      getValueByPath(obj, path) {
        let paths = path.split('.'); // [ xxx, yyy, zzz ]
        let res = obj
        let prop;
        while (prop = paths.shift()) {
          res = res[prop]
        }
        return res
      }
    }
    new Vue({
      el: '#app',
      data: {
        name: {
          firstName: '张三'
        }
      }
    })
  </script>
</body>

</html>